// 封装 axios
import axios from "axios";
import store from "@/store";
import { Toast } from "antd-mobile";
import router from "@/router";
import { clearUserInfo, setTokenState } from "@/store/modules/userSlice";
import { refreshTokenApi } from "@/apis/user";
// import { logout } from '@/store/actions'

export const http = axios.create({
  baseURL: process.env.REACT_APP_URL,
  timeout: 5000,
});

// 将来可以继续进行 拦截器 的处理

// 请求拦截器
http.interceptors.request.use((config) => {
  // 获取token
  // 注意：极客园h5项目中，login 存储的是一个对象，对象中的 token 属性，才是登录身份令牌
  const {  token, refresh_token }= store.getState().user.token;

  // 除了登录请求外，其他请求统一添加 token
  if (!config.url?.startsWith("/authorizations")) {
    // 此处，需要使用 非空断言 来去掉 headers 类型中的 undefined 类型
    config.headers!.Authorization = `Bearer ${token}`;
  } else if(config.method === 'put') {
    // 对于put请求登录接口的，则是刷新token请求，需要将refresh_token添加到headers中
    config.headers!.Authorization = `Bearer ${refresh_token}`;
  }

  return config;
});

// 登录超时，跳转到登录页
const loginTimeout = () => {
  Toast.show({
    content: "登录超时，请重新登录",
    duration: 1000,
    afterClose: () => {
      router.navigate(`/login?from=${window.location.pathname}`, {
        replace: true,
      });
      // 触发退出 action，将 token 等清除
      store.dispatch(clearUserInfo())
    },
  });
}

// 响应拦截器
http.interceptors.response.use(undefined, async (error) => {
  // 响应失败时，会执行此处的回调函数
  if (!error.response) {
    // 网路超时
    Toast.show({
      content: "网络繁忙，请稍后再试",
      duration: 1000,
    });
    return Promise.reject(error);
  }

  if (error.response.status === 401) {
    // token 过期，先判断是否有refresh_token，有的话，则刷新token，没有的话，则跳转到登录页
    const { refresh_token } = store.getState().user.token;
    if (!refresh_token) {
      loginTimeout();
      return Promise.reject(error);
    }
    try {
      const res = await refreshTokenApi();
      const token = {
        token: res.data.data.token,
        refresh_token
      }
      store.dispatch(setTokenState(token))
      // 刷新token成功，重新发送请求
      return http(error.config)
    } catch (e) {
      loginTimeout();
      return Promise.reject(e)
    }
  }

  return Promise.reject(error);
});
